﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using DevComponents.AdvTree;

namespace PolePosition.v3.Desktop.Grids
{
    public class BindableAdvTreeMultipleGrids : DevComponents.AdvTree.AdvTree
    {
       private Node m_FirstLevelNode;
        private bool m_ChildNodeDefined = false;
        private CellCollection m_ChildCells = null;
        private ColumnHeaderCollection m_ChildColumns = null;
        private string m_ChildCollectionPropertyName = null;

        public BindableAdvTreeMultipleGrids()
        {

        }

        [Browsable(false)]
        public System.Windows.Forms.BindingSource DataSource { get; set; }

        public void Bind()
        {
            DateTime startTime = DateTime.Now;
            DateTime stopTime;
            TimeSpan _ts;

            if (m_FirstLevelNode == null)
                m_FirstLevelNode = CopyFirstLevelNode(Nodes);

            this.Nodes.Clear();

            if (m_FirstLevelNode == null)
                return;

            PopulateData();

            stopTime = DateTime.Now;
            _ts = stopTime - startTime;
            System.Diagnostics.Debug.WriteLine("Build Tree Duration:" + _ts.Duration().TotalSeconds.ToString());
        }

        private void PopulateData()
        {
            int _Counter = 0;
            string _BindingColumnName;

            CellBindings _CellBindings;
            foreach (object _Entity in DataSource)
            {
                _BindingColumnName = this.Columns[0].ColumnName;
                _CellBindings = new CellBindings(null, _BindingColumnName, _Entity);

                Node _NewNode = new Node
                {
                    Tag = _CellBindings,
                    //TagString = m_FirstLevelNode.TagString,
                    Text = _CellBindings.GetDisplayText()
                };

                _NewNode.Style = m_FirstLevelNode.Style;

                for (int _ColumnCellIndex = 1; _ColumnCellIndex < m_FirstLevelNode.Cells.Count; _ColumnCellIndex++)
                {
                    Cell _Cell = m_FirstLevelNode.Cells[_ColumnCellIndex];
                    _BindingColumnName = this.Columns[_ColumnCellIndex].ColumnName;
                    _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _Entity);

                    _NewNode.Cells.Add(
                        new Cell()
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        });
                }

                Nodes.Add(_NewNode);
                
                //Create child nodes
                foreach(Node _TemplateNode in m_FirstLevelNode.Nodes)
                {
                    System.Windows.Forms.BindingSource _ChildDataSource = GetChildDataBindingSource(_Entity, _TemplateNode.TagString);
                    if (_ChildDataSource.Count == 0) 
                        continue;

                    Node _ParentChildNode = _TemplateNode.DeepCopy();
                    _ParentChildNode.Nodes.Clear();
                    _NewNode.Nodes.Add(_ParentChildNode);
                   
                    foreach (object _ChildEntity in _ChildDataSource)
                    {
                        _BindingColumnName = _TemplateNode.NodesColumns[0].ColumnName;
                        _CellBindings = new CellBindings(null, _BindingColumnName, _ChildEntity);

                        Node _ChildNode = new Node
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        };

                        _ChildNode.Style = _TemplateNode.Style;

                        for (int i = 1; i < _TemplateNode.Nodes[0].Cells.Count; i++)
                        {
                            Cell _Cell = _TemplateNode.Nodes[0].Cells[i];
                            _BindingColumnName = _TemplateNode.NodesColumns[i].ColumnName;
                            _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _ChildEntity);

                            _ChildNode.Cells.Add(new Cell()
                            {
                                Tag = _CellBindings,
                                Text = _CellBindings.GetDisplayText()
                            });
                        }

                        _ParentChildNode.Nodes.Add(_ChildNode);
                    }
                    
                }

                /*
                if (m_ChildNodeDefined)
                {
                    System.Windows.Forms.BindingSource _ChildDataSource;
                    _ChildDataSource = GetChildDataBindingSource(_Entity, m_ChildCollectionPropertyName);

                    //add columns first
                    ColumnHeader _NewHeader;
                    foreach (ColumnHeader _Header in m_ChildColumns)
                    {

                        _NewHeader = new ColumnHeader()
                        {
                            ColumnName = _Header.ColumnName,
                            Text = _Header.Text,
                        };
                        _NewHeader.Width.Absolute = _Header.Width.Absolute;
                        _NewNode.NodesColumns.Add(_NewHeader);
                    }

                    foreach (object _ChildEntity in _ChildDataSource)
                    {
                        _BindingColumnName = _NewNode.NodesColumns[0].ColumnName;
                        _CellBindings = new CellBindings(null, _BindingColumnName, _ChildEntity);

                        Node _ChildNode = new Node
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        };

                        for (int i = 1; i < m_ChildCells.Count; i++)
                        {
                            Cell _Cell = m_ChildCells[i];
                            _BindingColumnName = _NewNode.NodesColumns[i].ColumnName;
                            _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _ChildEntity);

                            _ChildNode.Cells.Add(new Cell()
                            {
                                Tag = _CellBindings,
                                Text = _CellBindings.GetDisplayText()
                            });
                        }

                        _NewNode.Nodes.Add(_ChildNode);
                    }
                }
                 */

                _Counter++;
                if (_Counter >= 100)
                    return;
            }
        }

/*
        private void PopulateData()
        {
            int _Counter = 0;
            string _BindingColumnName;

            CellBindings _CellBindings;
            foreach (object _Entity in DataSource)
            {
                _BindingColumnName = this.Columns[0].ColumnName;
                _CellBindings = new CellBindings(null, _BindingColumnName, _Entity);

                Node _NewNode = new Node
                {
                    Tag = _CellBindings,
                    //TagString = m_FirstLevelNode.TagString,
                    Text = _CellBindings.GetDisplayText()
                };

                for (int _ColumnCellIndex = 1; _ColumnCellIndex < m_FirstLevelNode.Cells.Count; _ColumnCellIndex++)
                {
                    Cell _Cell = m_FirstLevelNode.Cells[_ColumnCellIndex];
                    _BindingColumnName = this.Columns[_ColumnCellIndex].ColumnName;
                    _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _Entity);

                    _NewNode.Cells.Add(
                        new Cell()
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        });
                }

                this.Nodes.Add(_NewNode);

                if (m_ChildNodeDefined)
                {
                    System.Windows.Forms.BindingSource _ChildDataSource;
                    _ChildDataSource = GetChildDataBindingSource(_Entity, m_ChildCollectionPropertyName);

                    //add columns first
                    ColumnHeader _NewHeader;
                    foreach (ColumnHeader _Header in m_ChildColumns)
                    {

                        _NewHeader = new ColumnHeader()
                        {
                            ColumnName = _Header.ColumnName,
                            Text = _Header.Text,
                        };
                        _NewHeader.Width.Absolute = _Header.Width.Absolute;
                        _NewNode.NodesColumns.Add(_NewHeader);
                    }

                    foreach (object _ChildEntity in _ChildDataSource)
                    {
                        _BindingColumnName = _NewNode.NodesColumns[0].ColumnName;
                        _CellBindings = new CellBindings(null, _BindingColumnName, _ChildEntity);

                        Node _ChildNode = new Node
                        {
                            Tag = _CellBindings,
                            Text = _CellBindings.GetDisplayText()
                        };
                        
                        for (int i = 1; i < m_ChildCells.Count; i++)
                        {
                            Cell _Cell = m_ChildCells[i];
                            _BindingColumnName = _NewNode.NodesColumns[i].ColumnName;
                            _CellBindings = new CellBindings(_Cell.Tag as System.Windows.Forms.Control, _BindingColumnName, _ChildEntity);

                            _ChildNode.Cells.Add(new Cell()
                            {
                                Tag = _CellBindings,
                                Text = _CellBindings.GetDisplayText()
                            });
                        }

                        _NewNode.Nodes.Add(_ChildNode);
                    }
                }

                _Counter++;
                if (_Counter >= 100)
                    return;
            }
        }
*/

        private System.Windows.Forms.BindingSource GetChildDataBindingSource(object parentData, string childPropertyName)
        {
            if (parentData == null)
                ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("parentData"));

            System.Reflection.PropertyInfo _PropertyInfo;
            _PropertyInfo = parentData.GetType().GetProperty(childPropertyName);

            if (_PropertyInfo == null)
                ProjectCommon2.Helpers.ExceptionHelper.Throw(new Exception(childPropertyName + " property not found in entity."));

            object _Object;
            _Object = _PropertyInfo.GetValue(parentData, null);

            System.Windows.Forms.BindingSource _Binding;
            _Binding = new System.Windows.Forms.BindingSource();
            _Binding.DataSource = _Object;

            return _Binding;
        }

        private Node CopyFirstLevelNode(NodeCollection firstNode)
        {
            Node _FirstLevelNode = null;

            foreach (Node _Node in firstNode)
            {
                if (_Node.Level == 0)
                {
                    _FirstLevelNode = _Node;
                    break;
                }
            }

            if (_FirstLevelNode == null)
                return null;

            Node _NewFirstNode = _FirstLevelNode.DeepCopy();

            // hosted controls do not copy - so store in the tag
            for (int i = 0; i < _FirstLevelNode.Cells.Count; i++)
            {
                if (_FirstLevelNode.Cells[i].HostedControl != null)
                    _NewFirstNode.Cells[i].Tag = _FirstLevelNode.Cells[i].HostedControl;
            
            }


            // hosted controls do not copy - so store in the tag
            for (int i = 0; i < _FirstLevelNode.Nodes.Count; i++)
            {
                if (_FirstLevelNode.Nodes[i].Level == 1)
                {
                    // hosted controls do not copy - so store in the tag
                    for (int j = 0; j < _FirstLevelNode.Nodes[i].Nodes[0].Cells.Count; j++)
                    {
                        if (_FirstLevelNode.Nodes[i].Nodes[0].Cells[j].HostedControl != null)
                        {
                            _NewFirstNode.Nodes[i].Nodes[0].Cells[j].Tag = _FirstLevelNode.Nodes[i].Nodes[0].Cells[j].HostedControl;
                        }
                    }
                }
            }           


            
            /*foreach (Node _Node in _NewFirstNode.Nodes)
            {
                if (_Node.Level == 1)
                {
                    // hosted controls do not copy - so store in the tag
                    for (int i = 0; i < _Node.Cells.Count; i++)
                    {
                        if (_Node.Cells[i].HostedControl != null)
                        {
                            _Node.Cells[i].Tag = _Node.Cells[i].HostedControl;
                        }
                    }
                }
            }*/
            

            /*if (_FirstLevelNode.HasChildNodes && !string.IsNullOrEmpty(_FirstLevelNode.TagString))
            {
                m_ChildCollectionPropertyName = _FirstLevelNode.TagString;
                m_ChildCells = _FirstLevelNode.Nodes[0].Cells;

                // hosted controls do not copy - so store in the tag
                for (int i = 0; i < m_ChildCells.Count; i++)
                {
                    if (_FirstLevelNode.Nodes[0].Cells[i].HostedControl != null)
                    {
                        m_ChildCells[i].Tag = _FirstLevelNode.Nodes[0].Cells[i].HostedControl;
                    }
                }
            }*/

            return _NewFirstNode;
        }

        /*
        private Node CopyFirstLevelNode(NodeCollection nodes)
        {
            Node _FirstLevelNode = null;

            foreach (Node _Node in nodes)
            {
                if (_Node.Level == 0)
                {
                    _FirstLevelNode = _Node;
                    break;
                }
            }

            if (_FirstLevelNode == null)
                return null;

            Node _NewNode = _FirstLevelNode.DeepCopy();

            // hosted controls do not copy - so store in the tag
            for (int i = 0; i < _FirstLevelNode.Cells.Count; i++)
            {
                if (_FirstLevelNode.Cells[i].HostedControl != null)
                {
                    _NewNode.Cells[i].Tag = _FirstLevelNode.Cells[i].HostedControl;
                }
            }

            if (_FirstLevelNode.HasColumns)
                m_ChildColumns = _FirstLevelNode.NodesColumns;

            if (_FirstLevelNode.HasChildNodes && !string.IsNullOrEmpty(_FirstLevelNode.TagString))
            {
                m_ChildCollectionPropertyName = _FirstLevelNode.TagString;
                m_ChildCells = _FirstLevelNode.Nodes[0].Cells;

                // hosted controls do not copy - so store in the tag
                for (int i = 0; i < m_ChildCells.Count; i++)
                {
                    if ( _FirstLevelNode.Nodes[0].Cells[i].HostedControl != null)
                    {
                        m_ChildCells[i].Tag = _FirstLevelNode.Nodes[0].Cells[i].HostedControl;
                    }
                }
            }

            if (m_ChildCells != null && m_ChildColumns != null)
                m_ChildNodeDefined = true;

            return _NewNode;
        }
        */
        public object GetSelectedEntity()
        {
            if (this.SelectedNode == null)
                return null;

            return (this.SelectedNode.Tag as CellBindings).BoundEntity;
        }

        private class CellBindings
        {
            private System.Windows.Forms.Control m_HostedControl;
            private string m_BindingColumnName;
            object m_BoundEntity;

            public CellBindings(System.Windows.Forms.Control hostedControl, string bindingColumnName, object boundEntity)
            {
                m_HostedControl = hostedControl;
                m_BindingColumnName = bindingColumnName;
                m_BoundEntity = boundEntity;

            }

            public string FormatString { get; set; }
            public bool ReadOnly { get; set; }
            public object BoundEntity { get { return m_BoundEntity; } }


            public string GetDisplayText()
            {

                string _Text;

                if (m_BoundEntity is DataRowView)
                    _Text = GetValueString((DataRowView)m_BoundEntity, m_BindingColumnName);
                else
                    _Text = GetPropertyValueString(m_BoundEntity, m_BindingColumnName);

                //currently only type of hosted conntrol supported bill be ComboBoxEx
                if (m_HostedControl == null || typeof(DevComponents.DotNetBar.Controls.ComboBoxEx) != m_HostedControl.GetType())
                    return _Text;

                DevComponents.DotNetBar.Controls.ComboBoxEx _Combo;
                _Combo = m_HostedControl as DevComponents.DotNetBar.Controls.ComboBoxEx;

                if (_Combo.DataSource == null)
                    return _Text;

                string _DisplayMember = _Combo.DisplayMember;
                string _ValueMember = _Combo.ValueMember;

                if (string.IsNullOrEmpty(_ValueMember) || string.IsNullOrEmpty(_DisplayMember))
                    return _Text;

                if (_ValueMember == _DisplayMember)
                    return _Text;

                string _Value;
                //translate text based upon values stored in combo datasource (must be a binding source)
                foreach (object item in _Combo.DataSource as System.Windows.Forms.BindingSource)
                {
                    _Value = GetPropertyValueString(item, _ValueMember);

                    if (_Value == _Text)
                    {
                        _Text = GetPropertyValueString(item, _DisplayMember);
                        break;
                    }
                }

                return _Text;
            }

            public void ShowEdit(Cell cell)
            {
                if (m_HostedControl == null)
                    return;
                
            }

            private string GetPropertyValueString(object _Entity, string propertyName)
            {
                if (string.IsNullOrEmpty(propertyName))
                    return string.Empty;

                if (_Entity == null)
                    ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("Entity"));

                System.Reflection.PropertyInfo _PropertyInfo;
                _PropertyInfo = _Entity.GetType().GetProperty(propertyName);

                if (_PropertyInfo == null)
                    ProjectCommon2.Helpers.ExceptionHelper.Throw(new Exception(propertyName + " property not found in entity."));

                object _Object;
                _Object = _PropertyInfo.GetValue(_Entity, null);

                if (_Object == null)
                    return string.Empty;

                return _Object.ToString();
            }

            private string GetValueString(DataRowView _Entity, string propertyName)
            {
                if (string.IsNullOrEmpty(propertyName))
                    return string.Empty;

                if (_Entity == null)
                    ProjectCommon2.Helpers.ExceptionHelper.Throw(new ArgumentNullException("Entity"));

                return _Entity[propertyName].ToString();
            }
        }
    }
}
